#include "soaVideoRecordServer.h"

#include "public_define.h"
#include "adr_component.h"
#include "data_cache.h"
#include "dc_util.h"
#include <bitset>
#include <stdlib.h>
#include "common_opr_all.h"
#include "adr_trigger.h"

using namespace DcAdr;

SoaVideoRecordServer::SoaVideoRecordServer()
{

}

SoaVideoRecordServer::~SoaVideoRecordServer()
{

}

SoaVideoRecordServer &SoaVideoRecordServer::getInstance()
{
    static SoaVideoRecordServer info;
    return info;
}

void SoaVideoRecordServer::setPublishHandle(adr_component *component)
{
    m_component = component;
}

void SoaVideoRecordServer::RR_Init(const std::string &topic, const std::string &requestData, std::string &replyData)
{
    (void)topic;
    (void)requestData;
    Log_Info("[SoaVideoRecordServer] [RR_Init]");
    double beforeTime = 45 * 1000.0;
    //事件后多少秒
    double laterTime = 5 * 1000.0;
    DataCache::getInstance().setTopicDataInvildTime(ENCODE_SRV_H265_CAM0, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(ENCODE_SRV_H265_CAM1, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(ENCODE_SRV_H265_CAM2, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(ENCODE_SRV_H265_CAM3, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(ENCODE_SRV_H265_CAM10, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(ENCODE_SRV_H265_CAM8, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(HMI_TOPIC_BasicObjfusion32, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(HMI_TOPIC_BasicMapRoadScene, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(HMI_TOPIC_BasicStateFusion, beforeTime, laterTime);

    Soa::PB_Basc_VideoRecordServer_RR_Init_Out rrInitOut;
    rrInitOut.mutable_return_()->set_request_id(0);
    rrInitOut.mutable_return_()->set_rtncode(0);
    rrInitOut.mutable_return_()->set_session_id(0);
    rrInitOut.mutable_return_()->set_sourcemod(0);
    rrInitOut.mutable_return_()->set_vehfield(0);


    rrInitOut.SerializePartialToString(&replyData);
    
    return;

}

void SoaVideoRecordServer::RR_Uinit(const std::string &topic, const std::string &requestData, std::string &replyData)
{
    (void)topic;
    (void)requestData;
    Log_Info("[SoaVideoRecordServer] [RR_Uinit]");

    double beforeTime = 17000.0;
    //事件后多少秒
    double laterTime = 5000.0;
    DataCache::getInstance().setTopicDataInvildTime(ENCODE_SRV_H265_CAM0, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(ENCODE_SRV_H265_CAM1, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(ENCODE_SRV_H265_CAM2, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(ENCODE_SRV_H265_CAM3, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(ENCODE_SRV_H265_CAM10, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(ENCODE_SRV_H265_CAM8, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(HMI_TOPIC_BasicObjfusion32, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(HMI_TOPIC_BasicMapRoadScene, beforeTime, laterTime);
    DataCache::getInstance().setTopicDataInvildTime(HMI_TOPIC_BasicStateFusion, beforeTime, laterTime);


    Soa::PB_Basc_VideoRecordServer_RR_Uinit_Out rrUinitOut;
    rrUinitOut.mutable_return_()->set_request_id(0);
    rrUinitOut.mutable_return_()->set_rtncode(0);
    rrUinitOut.mutable_return_()->set_session_id(0);
    rrUinitOut.mutable_return_()->set_sourcemod(0);
    rrUinitOut.mutable_return_()->set_vehfield(0);
    

    rrUinitOut.SerializePartialToString(&replyData);

    return;
}

void SoaVideoRecordServer::RR_RequestVideoFile(const std::string &topic, const std::string &requestData, std::string &replyData)
{
    Log_Info("[SoaVideoRecordServer] [RR_RequestVideoFile]");

    Soa::PB_Basc_VideoRecordServer_RR_RequestVideoFile_Out rrRequestOut;
    rrRequestOut.mutable_return_()->set_request_id(0);
    rrRequestOut.mutable_return_()->set_rtncode(2001);
    rrRequestOut.mutable_return_()->set_session_id(0);
    rrRequestOut.mutable_return_()->set_sourcemod(0);
    rrRequestOut.mutable_return_()->set_vehfield(0);
    rrRequestOut.SerializePartialToString(&replyData);

    Soa::PB_Basc_VideoRecordServer_RR_RequestVideoFile_In rrRequest;
    if (!rrRequest.ParsePartialFromString(requestData))
    {
        Log_ERROR("Get_QueryFilePathInfo parse proto data failed , topic: {}", topic);
        return;
    }

    Soa::PB_VideoRequestParam videoRequestParam = rrRequest.videorequestparam();

    bool errParam = false;
    switch (videoRequestParam.triggertype())
    {
    case 1:
    case 2:
    case 3:
    {
        break;
    }
    default:   
        errParam = true;
        break;
    }
    if (errParam)
    {
        Log_Info("triggerType not match,return;", videoRequestParam.triggertype());
        return;
    }

    videoRequest(videoRequestParam);

    return;
}

/*
    1. 接收RPC请求 → 2. 解析验证参数 → 3. 配置录制参数 → 4. 设置摄像头 → 
    5. 添加数据收集 → 6. 触发录制任务 → 7. 处理特殊事件 → 8. 返回成功响应
*/
void SoaVideoRecordServer::videoRequest(const Soa::PB_VideoRequestParam &data)
{
    // 需求：
    //  0x1(0B000001): 前视120      ZF_     CAM8
    //  0x2(0B000010): 后视         ZR_     CAM10
    //  0x4(0B000100): 左前(周视)    ZFD_    CAM2 
    //  0x8(0B001000): 左后(周视)    ZRL_    CAM3 
    //  0x10(0B010000): 右前(周视)   ZFP_    CAM1 
    //  0x20(0B100000): 右后(周视)   ZRP_    CAM0 

    char uint8Buf[9];
    DcAdr::Util::uint8ToBinary(data.camera(), uint8Buf);
    Log_Info("DdsVideoServer trigger: {}  beforetime: {}  afterTime: {}  taskid: {} triggertype:{}",
             std::string(uint8Buf), data.beforetime(), data.backtime(), data.taskid(), data.triggertype());

    TriggerEventInfo trigger;
    trigger.triggerTime = Util::getMsTime();
    trigger.recordTime = CommonOprTime::getTime();
    trigger.beforeTime = data.beforetime() * 1000.0;
    trigger.laterTime = data.backtime() * 1000.0;
    trigger.taskId = data.taskid();
    trigger.triggerType = data.triggertype();    
    trigger.eventName = IT088_ONE;
    trigger.triggerStartTime =KTime::getPubTime();

    //add BA820
    TriggerEventInfo trigger_ba820;
    trigger_ba820.triggerTime = Util::getMsTime();
    trigger_ba820.recordTime = CommonOprTime::getTime();
    trigger_ba820.beforeTime = 15000;
    trigger_ba820.laterTime = 5000;
    trigger_ba820.taskId = data.taskid();
    trigger_ba820.triggerType = data.triggertype();    
    trigger_ba820.eventName = BA820_ONE;
    trigger_ba820.triggerStartTime =KTime::getPubTime();

    // 0x00-预警哨兵触发; 0x01-防擦防撞哨兵; 0x03-防盗哨兵触发
    // 0x01-预警哨兵，录制视频; 0x02-防擦防撞或防盗哨兵，录制视频和3d文件; 0x03-营地模式，录制视频和3d文件; 
    if (data.triggertype() == 0x02 || data.triggertype() == 0x03)
    {
        trigger.collectDatas.push_back(HMI_TOPIC_BasicObjfusion32);
        trigger.collectDatas.push_back(HMI_TOPIC_BasicMapRoadScene);
        trigger.collectDatas.push_back(HMI_TOPIC_BasicStateFusion);
    }

    uint8_t cameraValue = data.camera() & 0B100000;
    if (cameraValue == 0B100000)
    {
        trigger.collectDatas.push_back(ENCODE_SRV_H265_CAM0);
    }
    cameraValue = data.camera() & 0B010000;
    if (cameraValue == 0B010000)
    {
        trigger.collectDatas.push_back(ENCODE_SRV_H265_CAM1);
    }
    cameraValue = data.camera() & 0B001000;
    if (cameraValue == 0B001000)
    {
        trigger.collectDatas.push_back(ENCODE_SRV_H265_CAM3);
    }
    cameraValue = data.camera() & 0B000100;
    if (cameraValue == 0B000100)
    {
        trigger.collectDatas.push_back(ENCODE_SRV_H265_CAM2);
    }
    cameraValue = data.camera() & 0B000010;
    if (cameraValue == 0B000010)
    {
        trigger.collectDatas.push_back(ENCODE_SRV_H265_CAM10);
    }
    cameraValue = data.camera() & 0B000001;
    if (cameraValue == 0B000001)
    {
        trigger.collectDatas.push_back(ENCODE_SRV_H265_CAM8);
    }

    bool bIgnore = false;
    
    /*
        函数用于处理营地哨兵事件的优先级冲突。
        如果已有高优先级事件，则忽略低优先级事件。
        如果新事件优先级更高，则关闭旧事件文件并移除旧事件，为新事件做准备。
    */
    DataCache::getInstance().dealSentryEvent(trigger, bIgnore);
    if (!bIgnore)
    {
        DataCache::getInstance().acquireDataToSave(trigger);
    }
    if (data.triggertype() == 0x01 || data.triggertype() == 0x02 || data.triggertype() == 0x03)
    {
        double currTime = Util::getMsTime();
        std::shared_ptr<ProtoCondInfo_t> BA820ProtoCondInfo = std::make_shared<ProtoCondInfo_t>();
        if(DcAdr::AdrTrigger::getInstance().getOneEventProtoCondInfo(BA820_ONE,BA820ProtoCondInfo))
        {
            Log_Info("gd get {} collect success",BA820_ONE);
        }
        trigger_ba820.collectDatas =BA820ProtoCondInfo->collectData;
        if ((currTime - BA820ProtoCondInfo->trigLaterTime) > BA820ProtoCondInfo->limitTime)
        {
            DataCache::getInstance().acquireDataToSave(trigger_ba820);
        }
    }
}